Skip to content

fix(security): create atomic-write temp files with restrictive permissions#531

Open
qihan-bot wants to merge 1 commit intogoogleworkspace:mainfrom
qihan-bot:fix/atomic-write-permissions
Open

fix(security): create atomic-write temp files with restrictive permissions#531
qihan-bot wants to merge 1 commit intogoogleworkspace:mainfrom
qihan-bot:fix/atomic-write-permissions

Conversation

@qihan-bot
Copy link

Summary

  • Replace fs::write / tokio::fs::write with OpenOptions + mode(0o600) in both atomic_write and atomic_write_async, ensuring temp files containing credentials/tokens are only readable by the file owner before rename completes
  • Add sync_all() call before rename for crash-safety (data hits disk before the atomic swap)
  • Add test_atomic_write_permissions test verifying 0o600 on both sync and async code paths

Motivation

atomic_write is used by credential_store, oauth_config, and token_storage to persist sensitive data (encrypted credentials, OAuth tokens). The previous implementation used fs::write which creates files with umask-derived permissions (typically 0o644), leaving a brief window where other users on the system could read the temp file before rename.

Test plan

  • cargo test fs_util — all 5 tests pass including new permission test
  • cargo test — full suite 631 tests pass, no regressions
  • cargo clippy -- -D warnings — clean
  • Pre-commit hooks (clippy + fmt) pass
  • Pre-push hooks (check + test) pass

…sions

Temp files created by atomic_write / atomic_write_async now use
OpenOptions with mode 0o600 (owner-only read/write) instead of the
default umask-derived permissions.  This closes a brief window where
sensitive credential and token data could be readable by other users
before the rename completes.

Also adds sync_all() before rename for crash-safety and a new test
verifying the 0o600 permission on both sync and async paths.
@changeset-bot
Copy link

changeset-bot bot commented Mar 18, 2026

🦋 Changeset detected

Latest commit: 07b5b11

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@google-cla
Copy link

google-cla bot commented Mar 18, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@googleworkspace-bot googleworkspace-bot added the area: core Core CLI parsing, commands, error handling, utilities label Mar 18, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a security vulnerability by enhancing the atomic file writing mechanism. It ensures that temporary files, particularly those holding sensitive credentials or tokens, are created with highly restrictive permissions from the outset, preventing unauthorized access during the brief window before the atomic rename completes. Additionally, it improves data integrity by ensuring all data is written to disk before the final file swap.

Highlights

  • Security Fix: Replaced fs::write and tokio::fs::write with OpenOptions and mode(0o600) in atomic_write and atomic_write_async to ensure temporary files containing sensitive data are created with restrictive permissions (only readable by the file owner) before being renamed.
  • Crash Safety: Added sync_all() calls before the rename operation in both synchronous and asynchronous atomic write functions to ensure data is flushed to disk, improving crash-safety during atomic file swaps.
  • New Test Coverage: Introduced test_atomic_write_permissions to verify that the atomic_write and atomic_write_async functions correctly apply 0o600 permissions to temporary files on Unix systems.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances security by setting restrictive permissions (0o600) on temporary files used for atomic writes, preventing a race condition where sensitive data could be read by other users. The change is implemented for both synchronous and asynchronous atomic_write functions, includes a call to sync_all() for improved crash safety, and adds a test to verify the permissions on Unix systems. My review focuses on the platform-specific nature of the permission fix. While the changes are effective for Unix, they do not address the same vulnerability on other platforms like Windows. I've left comments suggesting a more cross-platform approach for a more complete security solution.

Comment on lines +51 to +54
#[cfg(unix)]
{
opts.mode(0o600);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This correctly applies restrictive permissions on Unix. However, this security fix is platform-specific and does not apply to Windows. On Windows, the temporary file for sensitive data will still be created with default permissions, which could allow other users on the system to read it. This leaves the security vulnerability open on Windows systems.

For a robust, cross-platform solution, I recommend using the tempfile crate (which is already a dev-dependency). It handles secure temporary file creation on major platforms by default, which would fully resolve this security issue.

Comment on lines +82 to +85
#[cfg(unix)]
{
opts.mode(0o600);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the synchronous version, this fix only applies restrictive permissions on Unix systems. The vulnerability of a readable temporary file remains on Windows.

To address this cross-platform, you could consider using a crate like async-tempfile, or refactor atomic_write to use the tempfile crate and then call it from this async function within a tokio::task::spawn_blocking block. This would ensure the temporary file is created securely on all supported platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Core CLI parsing, commands, error handling, utilities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants